using System;
using System.Collections;
using System.Collections.Generic;
using MyReactivity.Abstractions;

namespace MyReactivity
{
    public class ReactiveList<T> : IReadOnlyReactiveList<T>, IList<T>
    {
        private readonly List<T> _list;

        public ReactiveList() => _list = new List<T>();
        public ReactiveList(int capacity) => _list = new List<T>(capacity);
        public ReactiveList(IEnumerable<T> collection) => _list = new List<T>(collection);

        public T this[int index] 
        { 
            get => _list[index]; 
            set
            {
                ElementRemoved?.Invoke(index, _list[index]);

                _list[index] = value;

                ElementAdded?.Invoke(index, _list[index]);
            }
        }

        public int Count => _list.Count;
        public bool IsReadOnly => false;

        public event Action<int, T> ElementAdded;
        public event Action<int, T> ElementRemoved;

        public bool Contains(T element) => _list.Contains(element);

        public void Add(T element)
        {
            _list.Add(element);

            ElementAdded?.Invoke(_list.Count - 1, element);
        }

        public void Insert(int index, T element)
        {
            _list.Insert(index, element);

            ElementAdded?.Invoke(index, element);
        }

        public int IndexOf(T element) => _list.IndexOf(element);

        public bool Remove(T element)
        {
            var result = _list.Remove(element);
            var index = _list.IndexOf(element);

            ElementRemoved?.Invoke(index, element);

            return result;
        }
        public void RemoveAt(int index)
        {
            var element = _list[index];

            _list.RemoveAt(index);

            ElementRemoved?.Invoke(index, element);
        }

        public void Clear()
        {
            for (int i = _list.Count - 1; i >= 0; i--)
                RemoveAt(i);
        }

        public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex);

        public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
    }
}
